#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>

using namespace std;

class ThreadData
{
public:
    pthread_t tid;
    char namebuffer[64];
    int number;
};

class ThreadReturn
{
public:
    int code_quit;
    int code_result;
};

// void *routine(void *args)
// {
//     string name = static_cast<const char*>(args);
//     // const char* name = (const char*)args;
//     while (true)
//     {
//         cout << "我是新线程！name: " << name << endl;
//         sleep(1);
//     }
// }

void *routine(void *args)
{
    ThreadData* td = static_cast<ThreadData*>(args);
    int cnt = 5;
    while (cnt)
    {
        cout << "我是新线程！name: " << td->namebuffer << endl;
        cnt--;
        sleep(1);
        // exit(0); //不能终止线程，是用来终止进程的，这里任何一个执行流调用exit，会让所有的线程和主线程都终止。
    }

    //线程终止？如何终止？
    // pthread_exit(nullptr);
    // pthread_exit((void*)td->number);

    // ThreadReturn* tr = new ThreadReturn();
    // tr->code_quit = td->number;
    // tr->code_result = 1;
    //注意：返回值需要是void*
    // pthread_exit((void*)tr);
    
    //一般终止线程return即可
    return (void*)100; //1. 线程函数结束，return的时候，线程就算终止了
}

int main()
{
    vector<ThreadData*> threads;
#define NUM 10
    for (int i = 0; i < NUM; ++i)
    {
        ThreadData* td = new ThreadData();
        td->number = i+1;
        snprintf(td->namebuffer, sizeof(td->namebuffer), "%s:%d", "thread", i+1);
        pthread_create(&(td->tid), nullptr, routine, td);
        threads.push_back(td);
        // sleep(1);
    }

    for(auto& iter : threads)
    {
        cout << "create thread" << iter->namebuffer << " : " << iter->tid << "success" << endl;
    }


    //线程取消：pthread_cancel，只有执行中的线程才能被取消
    sleep(2);
    for(int i = 0; i < threads.size()/2; ++i)
    {
        pthread_cancel(threads[i]->tid);
        cout << "cancel: " << threads[i]->namebuffer << " success!" << endl;
    }
    
    for(auto& iter : threads)
    {
        void* ret = nullptr;
        //这里的第二个参数的类型需要是void**，因为外面的ret是void*，
        //如果传ret进去，那么函数内部改变ret并不会影响外面的值，所以需要传地址进去，那么ret的地址就是void**的了。
        pthread_join(iter->tid, &ret);
        cout << "join: " << iter->namebuffer << " success! code_quit--> " << (long long)ret << endl;
        //释放new的资源
        delete iter;
    }
    //线程等待：pthread_join
    // for(auto& iter : threads)
    // {
    //     pthread_join(iter->tid, nullptr);
    //     cout << "join: " << iter->namebuffer << " success!" << endl;
    //     //释放new的资源
    //     delete iter;
    // }

    // for(auto& iter : threads)
    // {
    //     void* ret = nullptr;
    //     pthread_join(iter->tid, &ret);
    //     cout << "join: " << iter->namebuffer << " success! --> " << (long long)ret << endl;
    //     //释放new的资源
    //     delete iter;
    // }

    // for(auto& iter : threads)
    // {
    //     ThreadReturn* ret = nullptr;
    //     //这里的第二个参数的类型需要是void**，因为外面的ret是void*，
    //     //如果传ret进去，那么函数内部改变ret并不会影响外面的值，所以需要传地址进去，那么ret的地址就是void**的了。
    //     pthread_join(iter->tid, (void**)&ret);
    //     cout << "join: " << iter->namebuffer << " success! code_quit--> " << ret->code_quit << " code_result-->" << ret->code_result << endl;
    //     //释放new的资源
    //     delete iter;
    // }

    cout << "main thread quit!" << endl;

    // while(true)
    // {
    //     cout << "我是主线程！name: main thread" << endl;
    //     sleep(1);
    // }

    return 0;
}


